package com.wmyg.antifake.fabric;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter;
import org.springframework.amqp.rabbit.support.MessagePropertiesConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(RabbitProperties.class)
public class RabbitConfig {

    @Autowired
    private RabbitProperties rabbitProperties;

    @Bean("connectionFactory")
    public ConnectionFactory getConnectionFactory() {
        com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = new com.rabbitmq.client.ConnectionFactory();
        rabbitConnectionFactory.setHost(rabbitProperties.getHost());
        rabbitConnectionFactory.setPort(rabbitProperties.getPort());
        rabbitConnectionFactory.setUsername(rabbitProperties.getUsername());
        rabbitConnectionFactory.setPassword(rabbitProperties.getPassword());
        ConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitConnectionFactory);
        return connectionFactory;
    }

    @Bean(name = "rabbitAdmin")
    public RabbitAdmin getRabbitAdmin() {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(getConnectionFactory());
        rabbitAdmin.setAutoStartup(true);
        return rabbitAdmin;
    }

    @Bean(name = "serializerMessageConverter")
    public MessageConverter getMessageConverter() {
        return new SimpleMessageConverter();
    }

    @Bean(name = "messagePropertiesConverter")
    public MessagePropertiesConverter getMessagePropertiesConverter() {
        return new DefaultMessagePropertiesConverter();
    }

    @Bean(name = "rabbitTemplate")
    public RabbitTemplate getRabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
        rabbitTemplate.setUseTemporaryReplyQueues(false);
        rabbitTemplate.setMessageConverter(getMessageConverter());
        rabbitTemplate.setMessagePropertiesConverter(getMessagePropertiesConverter());
        rabbitTemplate.setReplyAddress("fabricReplyMessageQueue");
        rabbitTemplate.setReceiveTimeout(60000);
        rabbitTemplate.setReplyTimeout(60000);
        return rabbitTemplate;
    }

    @Bean(name = "fabricMessageQueue")
    public Queue createFabricMessageQueue(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin) {
        Queue sendQueue = new Queue("fabricMessageQueue", true, false, false);
//        rabbitAdmin.declareQueue(sendQueue);
        return sendQueue;
    }

    @Bean(name="fabricMessageExchange")
    public Exchange createFabricMessageExchange(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        DirectExchange sendExchange = new DirectExchange("fabricMessageExchange",true,false);
//        rabbitAdmin.declareExchange(sendExchange);
        return sendExchange;
    }

    @Bean(name="fabricMessageBinding")
    public Binding createFabricMessageBinding(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        Map<String,Object> arguments = new HashMap<>();
        Binding sendMessageBinding =
                new Binding("fabricMessageQueue", Binding.DestinationType.QUEUE,
                        "fabricMessageExchange", "fabricMessage", arguments);
//        rabbitAdmin.declareBinding(sendMessageBinding);
        return sendMessageBinding;
    }

    @Bean(name = "messageListenerContainer")
    public MessageListenerContainer getMessageListenerContainer() {
        SimpleMessageListenerContainer messageListenerContainer = new SimpleMessageListenerContainer(getConnectionFactory());
        messageListenerContainer.addQueueNames("fabricReplyMessageQueue");
        messageListenerContainer.setMessageListener(getRabbitTemplate());
        messageListenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return messageListenerContainer;
    }

    @Bean(name = "fabricReplyMessageQueue")
    public Queue createFabricReplyMessageQueue(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin) {
        Queue replyQueue = new Queue("fabricReplyMessageQueue", true, false, false);
//        rabbitAdmin.declareQueue(replyQueue);
        return replyQueue;
    }

    @Bean(name="fabricReplyMessageExchange")
    public Exchange createfabricReplyMessageExchange(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        DirectExchange replyExchange = new DirectExchange("fabricReplyMessageExchange",true,false);
//        rabbitAdmin.declareExchange(replyExchange);
        return replyExchange;
    }

    @Bean(name="fabricReplyMessageBinding")
    public Binding createfabricReplyMessageBinding(@Qualifier("rabbitAdmin")RabbitAdmin rabbitAdmin)
    {
        Map<String,Object> arguments = new HashMap<>();
        Binding replyMessageBinding =
                new Binding("fabricReplyMessageQueue", Binding.DestinationType.QUEUE,
                        "fabricReplyMessageExchange", "fabricReplyMessage", arguments);
//        rabbitAdmin.declareBinding(replyMessageBinding);
        return replyMessageBinding;
    }

}
